#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// LightNode.h : interface of the LightNode class
//


#include "SmartEnum.h"
#include "TransformNode.h"
#include "Color.h"

// The two well-known kinds of OpenGL lights
BEGIN_ENUM(LightType)
    POSITIONAL, DIRECTIONAL
END_ENUM(LightType)

// ----------------------------------------------------------------------------
// The parameters that define a light in OpenGL 

struct LightParams
{
    LightType type;

    Color ambientColor;
    Color diffuseColor;
    Color specularColor;

    // Spot direction is Z axis of node frame
    int spotCutoff; // 0-90
    bool isSpot;

    float constantAttenuationFactor;
    float linearAttenuationFactor;
    float quadraticAttenuationFactor;
};


// ----------------------------------------------------------------------------
// Class "LightNode"
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//  We make it non-copyable because of the id member variable. We could define
//  a copy ctor. and an op= that set id=-1 for the destination material, but
//  this would probably lead to more confusing client code. So the way it is,
//  in order to copy a material you have to create a new one and copy its 
//  parameters with setParams and getParams
// ----------------------------------------------------------------------------


class LightNode : public TransformNode
{
public:

    // Ctor.
    LightNode();

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    Color getAmbientColor() const;
    void setAmbientColor(const Color& color);

    Color getDiffuseColor() const;
    void setDiffuseColor(const Color& color);

    Color getSpecularColor() const;
    void setSpecularColor(const Color& color);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    float getConstantAttenuationFactor() const;
    float getLinearAttenuationFactor() const;
    float getQuadraticAttenuationFactor() const;

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    void clearAttenuation();
    void setConstantAttenuationFactor(float newVal);
    void setLinearAttenuationFactor(float newVal);
    void setQuadraticAttenuationFactor(float newVal);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        
    void setSpotCutoff(int angle); // 0-90 degrees
    int getSpotCutoff() const; 
    
    bool isSpot() const;
    void setSpot(bool v=true);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    LightParams getParams() const;
    void setParams(const LightParams& newParams);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    void setId(int newId);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    void setType(LightType type);
    LightType getType() const;
    
    // Retrieve the light position or direction vector
    // (homogeneous) using a format that OpenGL likes
    void getPosOrDirVec(float dest[4]) const;

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

    // Updates the rendering context (typically OpenGL) with any changes
    // that this light might have experienced since the last time this
    // function was called. Params. that depend on the modelview matrix
    // (such as light direction, position, or spot direction) are always
    // updated, regardless of whether they have changed

    void updateParams();

    // --------------------------------------------------------------
    // Serialization
    void read(std::wistream& is) override;
    void write(std::wostream& os) const override;

protected:

    // Override. Returns true
    bool canBeDrawnImpl() const override;

    // Override.
    void draw(View3d * view) const override;

    // Override. Returns true
    bool isBoundedImpl() const override;

    // Override
    AABB getAabbLocalImpl() const override;

private:

    LightParams m_params;

    // Not serialized
    int m_id;
    bool m_needsUpdating;
};
